package com.lq.gitee;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Calculator {

    private static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight)
    {
        Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH);
        BufferedImage outputImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = outputImage.createGraphics();
        g2d.drawImage(resultingImage, 0, 0, null);
        g2d.dispose();
        return outputImage;
    }

    public static double[] imageToVector(BufferedImage image)
    {
        image = resizeImage(image, 100, 100);
        int width = image.getWidth();
        int height = image.getHeight();
        double[] vector = new double[width * height];
        int index = 0;
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int rgb = image.getRGB(x, y);
                vector[index++] = rgb;
            }
        }
        return vector;
    }

    public static double[] imageToVector(File imageFile) throws IOException
    {
        BufferedImage image = ImageIO.read(imageFile);
        return imageToVector(image);
    }

    // 计算余弦相似度
    public static double cosineSimilarity(double[] vecA, double[] vecB)
    {
        double dotProduct = 0.0;
        for (int i = 0; i < vecA.length; i++) {
            dotProduct += vecA[i] * vecB[i];
        }

        double normA = 0.0;
        double normB = 0.0;
        for (double v : vecA) {
            normA += v * v;
        }
        for (double v : vecB) {
            normB += v * v;
        }
        normA = Math.sqrt(normA);
        normB = Math.sqrt(normB);

        if (normA == 0 || normB == 0) {
            return 0.0;
        }
        return dotProduct / (normA * normB);
    }

    public static double recognitionNumber(Map<String, double[]> vecMap, File imageFile) throws IOException
    {
        List<BufferedImage> numbers = PreProcessor.toNumbers(imageFile);
        StringBuilder result = new StringBuilder();
        for (BufferedImage number : numbers) {
            double[] vec = imageToVector(number);
            double maxS = -1;
            String value = null;
            for (Map.Entry<String, double[]> nameVec : vecMap.entrySet()) {
                double[] v = nameVec.getValue();
                double s = cosineSimilarity(v, vec);
                if (s > maxS) {
                    maxS = s;
                    value = nameVec.getKey();
                }
            }
            result.append(value);
        }
        return Double.parseDouble(result.toString());
    }

    public static void main(String[] args) throws IOException
    {
        // 加载样本数据
        Map<String, double[]> vec = new HashMap<>();
        for (File file : Configuration.SAMPLES_FOLDER.listFiles()) {
            double[] vector = imageToVector(file);
            String name = file.getName().substring(0, file.getName().lastIndexOf("."));
            if (name.equals("dot")) {
                name = ".";
            }
            vec.put(name, vector);
        }
        double all = 0d;
        for (File imageFile : Configuration.MONEY_VALUE_FOLDER.listFiles()) {
            double value = recognitionNumber(vec, imageFile);
            all += value;
            System.out.println(value);
        }
        System.out.println("all = " + all);
    }

}
